package demo.topic12.introspector;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;

/**
 * 工厂模式实现
 * 通过内省API来装配一个Bean对象
 */
public class BeanFactory {
    private static Properties prop = new Properties();

    // 静态代码块读取配置文件
    static {
        // 读取需要放在 src/main/resources 下
        InputStream in = Thread.currentThread().getContextClassLoader()
                .getResourceAsStream("config.properties");
        try {
            prop.load(in);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static Object getBean(String name) {
        Object bean = null;
        String beanName = prop.getProperty(name);
        try {
            // 通过Class类的forName()方法，得到Class的类对象（反射）
            Class<?> aClass = Class.forName(beanName);
            // 使用Class类进行对象的实例化操作，调用无参构造器进行实例化
            bean = aClass.newInstance();
            // 通过类信息获取javaBean的描述信息
            BeanInfo beanInfo = Introspector.getBeanInfo(aClass);
            // 通过javaBean描述信息，获取该类的所有属性描述器
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            for (int i = 0; i < propertyDescriptors.length; i++) {
                String propertyName = propertyDescriptors[i].getName();
                Method writeMethod = propertyDescriptors[i].getWriteMethod();
                // 匹配前缀
                String namePrefix = name.replaceAll("^(\\w+)\\.\\w+", "$1");
                if("class".equals(propertyName)) continue;
                String finalName = namePrefix+"."+propertyName;
                // 调用属性set方法
                writeMethod.invoke(bean, prop.getProperty(finalName));
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IntrospectionException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }

        return bean;
    }
}
